package com.nulldev.util.java.swing.extSwing.iNotify;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.LinkedList;

import javax.swing.JPanel;

import com.nulldev.util.java.swing.canvas.PaintMethod;
import com.nulldev.util.java.swing.canvas.SmoothCanvas;
import com.nulldev.util.java.swing.font.FontManager;
import com.nulldev.util.math.MathUtil;
import com.nulldev.util.promise.Promiser;
import com.nulldev.util.promise.noresult.NoResultPromise;

public class iNotify extends SmoothCanvas {
	
	private final LinkedList<Message> messages = new LinkedList<Message>();
	
	public iNotify() {
		super();
		this.usePaintMethod(PaintMethod.REPAINT);
		this.setAAEnabled(true);
		this.setFPS(10);
		super.addMouseListener(new MouseListener() {
			
			@Override
			public void mouseReleased(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON1) {
					iNotify.this.onClick(e.getX(), e.getY());
				}
			}
			
			@Override
			public void mousePressed(MouseEvent e) {
			}
			
			@Override
			public void mouseExited(MouseEvent e) {
			}
			
			@Override
			public void mouseEntered(MouseEvent e) {
			}
			
			@Override
			public void mouseClicked(MouseEvent e) {
			}
		});
	}
	
	@Override
	public boolean contains(final int x, final int y) {
		return true;
	}
	
	public boolean addMessage(final Message message) {
		return this.messages.add(message);
	}
	
	public boolean requireOverride(final int x, final int y) {
		final int h = messages.size() * 45;
		return (y <= h);
	}
	
	public void onClick(final int x, final int y) {
		final int meSize = messages.size();
		int ly = 0;
		if (meSize > 0) {
			for (final Message m : messages) {
				if (MathUtil.between(x, getWidth() - 40, getWidth() - 25) && MathUtil.between(y, ly + 10, ly + 10 + 25 + 25) && !m.autoEnds()) {
					this.messages.remove(m);
					if (!this.hasNotifications()) {
						this.lastY = 1;
						this.setVisible(false);
					}
				}
				ly += 45;
			}
		}
	}
	
	public boolean hasNotifications() {
		return !this.messages.isEmpty();
	}
	
	//public abstract int getWidth();
	
	//public abstract int getHeight();
	
	private int lastY = (hasNotifications() ? 1 : 45);
	
	public int getLastHeight() {
		return this.lastY;
	}
	
	@Override
	public Dimension getSize() {
		return new Dimension((int) super.getPreferredSize().getWidth(), getLastHeight());
	}
	
	@Override
	public Dimension getPreferredSize() {
		return new Dimension((int) super.getPreferredSize().getWidth(), getLastHeight());
	}
	
	public void render(final Graphics g) {
		if (this.hasNotifications() && !this.isVisible()) {
			this.setVisible(true);
		}
		final Font f = FontManager.getFontSet();
		//((Graphics2D)g).setComposite(AlphaComposite.SrcOver.derive(0.95f));
		g.setFont(f);
		int y = 0;
		//g.setColor(Color.ORANGE);
		//g.fillRect(0, y, getWidth(), 45);
		//g.setColor(Color.BLACK);
		//g.drawString("UI testing enabled!", 5, (int) (y + f.getSize2D()));
		//g.drawString("This launch process has now halted!", 5, (int) (y + f.getSize2D() + f.getSize2D() + 5));
		//g.drawRect(getWidth() - 40, y + 10, 25, 25);
		for (final Message m : this.messages) {
			g.setColor(m.getType().getColor());
			g.fillRect(0, y, getWidth(), 45);
			g.setColor(Color.BLACK);
			g.drawString(m.getTitle(), 5, (int) (y + f.getSize2D()));
			g.drawString(m.getMessage(), 5, (int) (y + f.getSize2D() + f.getSize2D() + 5));
			if (!m.autoEnds()) {
				g.setColor(Color.GRAY);
				g.fillRect(getWidth() - 40, y + 10, 25, 25);
				g.setColor(Color.BLACK);
				g.drawString("" + ((char) 215), getWidth() - g.getFontMetrics().stringWidth((char) 215 + "") - 23, y + 29);
			}else {
				if (!m._init_end_isWaiting()) {
					Promiser.promise(new NoResultPromise() {
						
						@Override
						public void run() throws Throwable {
							Thread.sleep(m.endsAfter());
							messages.remove(m);
							if (!iNotify.this.hasNotifications()) {
								iNotify.this.lastY = 1;
								iNotify.this.setVisible(false);
							}
						}
						
						@Override
						public void error(Throwable throwable) {
							throwable.printStackTrace();
							messages.remove(m);
						}
					});
					m.init_end_wait();
				}
			}
			y += 45;
		}	
		
		this.lastY = y;
	}

	@Override
	public void drawCanvas(final Graphics2D g2d) {
		//.out.println("render();");
		this.render(g2d);
	}
}
